package tr.edu.boun.phys.springmassmodel.UI;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;

import tr.edu.boun.phys.springmassmodel.Mass;
import tr.edu.boun.phys.springmassmodel.SpringMassModel;
import tr.edu.boun.phys.springmassmodel.Vector2D;
import tr.edu.boun.phys.springmassmodel.UI.PropertiesWindow.PropertiesWindow;

public class DisplayMouseListener implements MouseListener, MouseMotionListener {
	
	private ResourceManager rm;
	private Display display;
	private PropertiesWindow propertiesWindow;
	private SpringMassModel model;
	private int nMasses;
	
	private boolean dragging = false;
	private int selectedMassConstraint = Mass.NO_CONSTRAINT;
	
	private double ix, iy;
	private Vector2D initMassLocation;
	
	private static final int NONE = -1;
	
	public DisplayMouseListener(ResourceManager rm) {
		this.rm = rm;
		this.display = this.rm.getDisplay();
		this.propertiesWindow = rm.getPropertiesWindow();
		this.model = rm.getStringModel();
		this.nMasses = model.getNumberOfMasses();
		this.initMassLocation = new Vector2D(0.0, 0.0);
	}
	
	 

	public void mouseClicked(MouseEvent me) {
		if( me.getClickCount() == 2 ) {
			Vector2D cursorLocation = new Vector2D(me.getX(), me.getY());
			Vector2D massLocation = display.v2m(cursorLocation);
			Vector2D velocity = new Vector2D(0.0, 0.0);
			Mass m = new Mass(1.0, massLocation, velocity);
			model.addMass( m );
			display.repaint();
		}
		
	}

	public void mousePressed(MouseEvent me) {
		int n = mouseOnMass(me);
		if( n != -1 ) {
			rm.setSelectedMass( model.getMass(n), n );
			initMassLocation.x = model.getMass(n).getLocation().x;
			initMassLocation.y = model.getMass(n).getLocation().y;
			
			selectedMassConstraint = rm.getSelectedMass().getConstraint();
			
			display.repaint();
		} else {
			//rm.getSelectedMass().setConstraint(selectedMassConstraint);
			rm.setSelectedMass( null, 0 );
			display.repaint();
			
			propertiesWindow.selectMass( null , n);
		}
		ix = me.getX();
		iy = me.getY();
	}

	public void mouseReleased(MouseEvent arg0) {
		dragging = false;
	}

	public void mouseEntered(MouseEvent arg0) {
		
	}

	public void mouseExited(MouseEvent arg0) {
		
	}
	
	
	/*bu tasima isiyle ugras iste...*/
	public void mouseDragged(MouseEvent me) {
		int n = mouseOnMass(me);
		if( n != NONE ) {
			
		}
		
		if( rm.getSelectedMass() != null ) {
			Mass mass = rm.getSelectedMass();
			mass.setConstraint(Mass.NO_FREEDOM);
			double oldX = display.m2v(initMassLocation).x;
			double oldY = display.m2v(initMassLocation).y;
			double newX = display.m2v(initMassLocation).x + (me.getX()-ix);
			double newY = display.m2v(initMassLocation).y + (me.getY()-iy);
			switch( mass.getConstraint() ) {
			case Mass.X_ONLY:
				mass.move( display.v2m(new Vector2D(newX, oldY)) );
				break;
			case Mass.Y_ONLY:
				mass.move( display.v2m(new Vector2D(oldX, newY)) );
				break;
			case Mass.NO_CONSTRAINT:
				mass.move( display.v2m(new Vector2D(newX, newY)) );
				break;
			case Mass.NO_FREEDOM:
				mass.move( display.v2m(new Vector2D(newX, newY)) );
				break;
			}
			display.repaint();					
		}
		
	}
	
	public void mouseMoved(MouseEvent me) {
		int n = mouseOnMass(me);
		nMasses = model.getNumberOfMasses();
		if( n != NONE ) {
			if( display.getFocusedMass() != model.getMass(n) ) {
				display.setFocusedMass( model.getMass(n) );
				display.repaint();
			}
		} else {
			if( display.getFocusedMass() != null &&
				display.getFocusedMass() == rm.getSelectedMass() ) {
				//System.out.println("secilen terk edildi");
				rm.getSelectedMass().setConstraint(selectedMassConstraint);
			}
			if( display.getFocusedMass() != null) {
				display.setFocusedMass( null );
				display.repaint();
			}			
		}
	}
	
	private int mouseOnMass(MouseEvent me) {		
		for(int i=0; i<nMasses; i++) {
			Mass m = model.getMass(i);			
			Vector2D v = display.m2v( m.getLocation() );
			
			
			double radius = display.m2v(m.getM());
			Ellipse2D.Double circle = new Ellipse2D.Double(v.getX()-radius/2, v.getY()-radius/2, radius, radius);
			
			if(circle.contains( me.getPoint() )) {
				return i;
			}
		}		
		return NONE;		
	}

}